using System;
using System.Collections.Generic;
using System.Text;
using Decav.Gatsb.Locales;

namespace Decav.Gatsb
{
    /// <summary>
    /// Defines a locale that Gatsb functions in, such as a city or region.
    /// </summary>
    public abstract class Locale
    {
        #region Statics

        static Locale()
        {
            AddLocale(new NewYorkCityLocale());
        }

        private static void AddLocale(Locale locale)
        {
            _locales.Add(locale.Id, locale);
        }

        private static Dictionary<Guid, Locale> _locales = new Dictionary<Guid, Locale>();
        private static Locale _defaultLocale = new NeutralLocale();

        /// <summary>
        /// Gets a locale given its unique identifier.
        /// </summary>
        /// <param name="localeId">The unique identifier of the locale.</param>
        /// <returns>The locale specified by the ID.</returns>
        public static Locale GetLocale(Guid localeId)
        {
            Locale locale = null;
            if (!_locales.TryGetValue(localeId, out locale))
                locale = DefaultLocale;

            return locale;
        }

        /// <summary>
        /// Gets the default <see cref="NeutralLocale"/>.
        /// </summary>
        public static Locale DefaultLocale
        {
            get
            {
                return _defaultLocale;
            }
        }

        #endregion

        #region Non-static Members

        protected Locale(string displayName, Guid id)
        {
            if (displayName == null)
                throw new ArgumentNullException("displayName");

            _displayName = displayName;
            _id = id;
        }

        private Guid _id;
        private string _displayName;

        /// <summary>
        /// Gets the locale's unique identifier.
        /// </summary>
        public Guid Id
        {
            get
            {
                return _id;
            }
        }

        /// <summary>
        /// Gets the locale's display name.
        /// </summary>
        public string DisplayName
        {
            get
            {
                return _displayName;
            }
        }

        /// <summary>
        /// Gets the display name of the locale.
        /// </summary>
        /// <returns>The <see cref="DisplayName"/>.</returns>
        public override string ToString()
        {
            return DisplayName;
        }

        /// <summary>
        /// Formats the name of a <see cref="Location"/> into the name for the current
        /// locale.
        /// </summary>
        /// <param name="location">The location to format the name for.</param>
        /// <param name="format">The method that should be used to format the location name.</param>
        /// <returns>The name of the location, formatted to the locale.</returns>
        public abstract string FormatLocationName(Location location, LocationNameFormat format);

        /// <summary>
        /// Formats the name of a <see cref="Location"/> into the name for the current
        /// locale.
        /// </summary>
        /// <param name="location">The location to format the name for.</param>
        /// <returns>The name of the location, formatted to the locale.</returns>
        public string FormatLocationName(Location location)
        {
            return FormatLocationName(location, LocationNameFormat.Default);
        }

        /// <summary>
        /// Parses textual input of a search into a <see cref="LocationSearchCriteria"/> using rules
        /// for the current locale.
        /// </summary>
        /// <param name="searchString">The search to conduct.</param>
        /// <returns>The search criteria defined by the search string.</returns>
        public abstract LocationSearchCriteria ParseSearchString(string searchString);

        #endregion
    }
}
